<template>
    <!--  https://github.com/vasturiano/3d-force-graph  -->
    <div id="3d-graph"></div>
</template>
<script setup>
import Mock from "mockjs";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
import * as THREE from "three";
import SpriteText from "three-spritetext";
import ForceGraph3D from "3d-force-graph";
import { onMounted } from "vue";
import bigdata from "./data.js";

onMounted(() => {
    function generateRandomData(numNodes, numLinks) {
        const nodes = [];
        const links = [];

        // 生成节点
        for (let i = 1; i <= numNodes; i++) {
            nodes.push({
                id: `id${i}`,
                name: `name${i}`,
                val: i, // 或者你可以根据需要生成其他值
            });
        }

        // 随机生成链接
        const possibleLinks = [];
        for (let i = 1; i <= numNodes; i++) {
            for (let j = i + 1; j <= numNodes; j++) {
                possibleLinks.push({ source: `id${i}`, target: `id${j}` });
            }
        }

        // 随机选择指定数量的链接
        const shuffledLinks = possibleLinks.sort(() => 0.5 - Math.random());
        for (let i = 0; i < Math.min(numLinks, shuffledLinks.length); i++) {
            links.push(shuffledLinks[i]);
        }

        return {
            nodes,
            links,
        };
    }

    // 调用函数生成包含1000个节点和随机链接的数据
    const numNodes = 500; // 节点数量
    const numLinks = 1000; // 随机生成的链接数量（可以根据需要调整）
    const gData = generateRandomData(numNodes, numLinks);

    const elem = document.getElementById("3d-graph");
    const Graph = new ForceGraph3D(elem)
        .nodeThreeObject((node) => {
            if (node.hasImg) {
                // const geometry = new THREE.CircleGeometry(7, 132) // 半径为5，分段数为32
                const geometry = new THREE.SphereGeometry(7, 32, 32);
                let randomNum = Math.floor(Math.random() * 10) + 1;
                const imgTexture = new THREE.TextureLoader().load(
                    `https://api.simpleqq.com/avatar/${randomNum}.jpg`,
                );
                // const imgTexture = new THREE.TextureLoader().load(`./3.jpg`)
                imgTexture.colorSpace = THREE.SRGBColorSpace;
                // 创建材质并设置纹理
                const material = new THREE.MeshBasicMaterial({
                    map: imgTexture, // 设置纹理贴图
                    side: THREE.DoubleSide, // 如果需要双面显示，设置为双面渲染
                });

                // 创建网格模型
                const mesh = new THREE.Mesh(geometry, material);

                // const material2 = new THREE.SpriteMaterial({ map: imgTexture })
                // const sprite = new THREE.Sprite(material2)
                // sprite.scale.set(12, 12)
                // return sprite
                return mesh;
            } else return null;
        })
        .graphData(bigdata)
        .nodeAutoColorBy("user")
        .nodeLabel((node) => {
            if (node.label) {
                return node.label;
            } else {
                return Mock.mock("@cname");
            }
        })
        .nodeRelSize(5)
        .nodeResolution(10)
        .linkWidth(1)
        // .linkDirectionalParticles(2)
        // .linkDirectionalParticleWidth(0.8)
        // .linkDirectionalParticleSpeed(0.006)
        .onNodeDragEnd((node) => {
            node.fx = node.x;
            node.fy = node.y;
            node.fz = node.z;
        })
        .onNodeClick((node) => {
            const distance = 200; // 相机与节点的距离
            const distRatio = 1 + distance / Math.hypot(node.x, node.y, node.z);
            Graph.cameraPosition(
                {
                    x: node.x * distRatio,
                    y: node.y * distRatio,
                    z: node.z * distRatio,
                }, // 新的相机位置
                node, // 相机注视点
                2000, // 动画持续时间（毫秒）
            );
        });

    /*const Graph = new ForceGraph3D(document.getElementById('3d-graph'))
    .nodeThreeObject(({ img }) => {
      // 创建圆形几何体
      // const geometry = new THREE.CircleGeometry(7, 132) // 半径为5，分段数为32
      const geometry =  new THREE.SphereGeometry(7, 32, 32);
      let randomNum = Math.floor(Math.random() * 10) + 1
      // const imgTexture = new THREE.TextureLoader().load(`https://api.simpleqq.com/avatar/${randomNum}.jpg`)
      const imgTexture = new THREE.TextureLoader().load(`./3.jpg`)
      imgTexture.colorSpace = THREE.SRGBColorSpace
      // 创建材质并设置纹理
      const material = new THREE.MeshBasicMaterial({
        map: imgTexture, // 设置纹理贴图
        side: THREE.DoubleSide // 如果需要双面显示，设置为双面渲染
      })

      // 创建网格模型
      const mesh = new THREE.Mesh(geometry, material)
      // const material2 = new THREE.SpriteMaterial({ map: imgTexture })
      // const sprite = new THREE.Sprite(material2)
      // sprite.scale.set(12, 12)
      // return sprite
      return mesh
    }).graphData(gData).nodeLabel('id')
    .nodeAutoColorBy('group')
    .linkThreeObjectExtend(true)
    .linkThreeObject(link => {
      // extend link with text sprite
      // const sprite = new SpriteText(`${link.source} ---- ${link.target}`)
      const sprite = new SpriteText(`同行${Math.floor(Math.random() * 10) + 1}天${Math.floor(Math.random() * 10) + 1}次`)
      sprite.color = 'lightgrey'
      sprite.fontSize = 50
      sprite.textHeight = 4
      return sprite
    })
    .linkPositionUpdate((sprite, { start, end }) => {
      const middlePos = Object.assign(...['x', 'y', 'z'].map(c => ({
        [c]: start[c] + (end[c] - start[c]) / 2 // calc middle point
      })))

      // Position sprite
      Object.assign(sprite.position, middlePos)
    })
    Graph.d3Force('charge').strength(-120);*/
});
</script>

<style scoped>
#3d-graph {
    width: 100vw;
    height: 100vh;
}
</style>
